
#include "unp.h"

#define SAP_NAME    "sap.mcast.net"
#define SAP_PORT    9875


void loop(int sockfd, socklen_t sa_len);
void AddToMultiGroup();

int main(int argc, char * argv[]) {

    // AddToMultiGroup();

    // int sockfd = -1;
    // const int on = 1;
    
    // socklen_t sockaddr_len = 0;
    // struct sockaddr_in *sockaddr;

    // sockfd = Udp_client(SAP_NAME, SAP_PORT, (void ** )&sockaddr, &sockaddr_len);
    // if (sockfd >= 0) {

    //     printf("connect success\n");

    //     // continue
    //     setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

    //     bind(sockfd, (struct sockaddr *)sockaddr, sizeof(struct sockaddr_in));

    //     mcast_join(sockfd, (struct sockaddr * )sockaddr, sockaddr_len, NULL, 0);

    //     loop(sockfd, sockaddr_len);

    //     close(sockfd);
    // }
    // else {

    //     printf("connect failure and error_code : %d\n", errno);
    // }
    return EXIT_SUCCESS;
}

void loop(int sockfd, socklen_t sa_len) {

    socklen_t len;
    ssize_t n;

    char * ptr;
    struct sockaddr * sa;

    struct sap_packet {

        uint32_t    sap_header;
        uint32_t    sap_src;
        char        sap_data[BUFFER_SIZE];
    }buf;

    sa = malloc(sa_len);
    for (;;) {

        len = sa_len;
        n = recvfrom(sockfd, &buf, sizeof(buf) - 1, 0, sa, &len);

        ((char * )&buf) [n] = 0;

        buf.sap_header = ntohl(buf.sap_header);
        printf("From %s hash 0x%04x\n", sock_ntop((struct sockaddr * )sa, len), (buf.sap_header & SAP_HASH_MASK));

        if ( ( (buf.sap_header & SAP_VERSION_MASK) >> SAP_VERSION_SHIFT ) > 1) {

            printf("[ERROR].... version field not 1 (0x%08x)", buf.sap_header);
            continue;
        }
        if (buf.sap_header & SAP_IPV6) {

            printf("[ERROR]... IPV6");
            continue;
        }
        if (buf.sap_header & (SAP_DELETE | SAP_ENCRYPTED | SAP_COMPRESSED)) {

            printf("[ERROR] ... can't parse this packet type (0x%08x)", buf.sap_header);

            continue;
        }
        ptr = buf.sap_data + ((buf.sap_header & SAP_AUTHLEN_MASK) >> SAP_AUTHLEN_SHIFT);

        if (strcmp(ptr, "application/sdp") == 0) {

            ptr += 16;
        }
        printf("%s\n", ptr);
    }
}

void AddToMultiGroup() {

    int udpsocket = socket(AF_INET, SOCK_DGRAM, 0);

    struct sockaddr_in addr;
    bzero(&addr, sizeof(struct sockaddr_in));

    const char * local_ip = "192.168.16.5";
    const char * multicast_ip = "239.255.1.2";

    int local = 8888;

    addr.sin_family = AF_INET;
    addr.sin_port   = htons(local);
    addr.sin_addr.s_addr = inet_addr(multicast_ip);

    printf("%d\n", bind(udpsocket, (struct sockaddr * )&addr, sizeof(addr)));

    int reuseOn = 1;
    setsockopt(udpsocket, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));

    struct ip_mreq mreq;
    bzero(&mreq, sizeof(mreq));

    mreq.imr_multiaddr.s_addr = inet_addr(multicast_ip);
    mreq.imr_interface.s_addr = inet_addr(local_ip);

    setsockopt(udpsocket, IPPROTO_UDP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

    loop(udpsocket, sizeof(struct sockaddr_in));

    setsockopt(udpsocket, IPPROTO_UDP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
    close(udpsocket);
}

// gcc -g mysdr.c unp.c -o mysdr -I./